#include "app_pool.h"
#include "log.h"
#include <mqueue.h>
#include <pthread.h>
#include <stdlib.h>

// 消息队列
static mqd_t mq;

#define MQUEUE_MAXMSG 10
// 名字前一定要以 / 开头
#define MQUEUE_QUEUE_NAME "/gateway_pool_queue"

// 定义一个数组 指针的原因是  线程池中线程的数量是可变的
static pthread_t *thread_pool;

// 
int g_thread_num;

/**
 * @brief 线程池的工作：每个线程去争抢任务，有任务了去执行任务
 */
void *thread_func(void *arg)
{
    while (1)
    {
        task_t task;
        // 每个线程去争抢任务
        mq_receive(mq, (char *)&task, sizeof(task), NULL);
        // 如果争抢到了
        if (task.func != NULL)
        {
            task.func(task.arg);
        }
        
    }
}

/**
 * @brief 线程池的初始化
 * 
 * @param thread_num 线程池中线程的数量
 */

int app_pool_init(int thread_num)
{
    // 得到线程池中线程的数量，为了后期的销毁
    g_thread_num = thread_num;
    // 初始化队列
    // 1 设定队列属性
    struct mq_attr attr;
    attr.mq_maxmsg = MQUEUE_MAXMSG;
    attr.mq_msgsize = sizeof(task_t);
    // 2 创建队列
    mq = mq_open(MQUEUE_QUEUE_NAME, O_CREAT | O_RDWR, 0644, &attr);
    if (mq == -1)
    {
        perror("创建队列失败");
        return -1;
    }
    
    // 初始化线程
    thread_pool = (pthread_t *)malloc(sizeof(pthread_t) * thread_num);
    for (int i = 0; i < thread_num; i++)
    {
        pthread_create(&thread_pool[i], NULL, thread_func, NULL);
    }
    
    return 0;
}

/**
 * @brief 向线程池注册一个任务
 * 
 * @param task 任务
 */
int app_pool_register(void (*task_func)(void *arg),void *arg)
{
    // 把需求方的任务定义和参数组合为一个任务结构体，再把任务提交到队列中
    task_t task;
    task.func = task_func;
    task.arg = arg;
    // 把任务提交到队列中
    int res = mq_send(mq, (char *)&task, sizeof(task), 0);
    if (res == -1)
    {
        perror("加入线程池队列失败");
        return -1;
    }
    return 0;
}

/**
 * @brief 线程池的销毁
 */
void app_pool_destroy(void)
{
    // 先把线程池中的线程全部销毁
    for (int i = 0; i < g_thread_num; i++)
    {
        pthread_cancel(thread_pool[i]);
        pthread_join(thread_pool[i], NULL);
    }
    g_thread_num = 0;
    // 销毁队列
    mq_close(mq);
    mq_unlink(MQUEUE_QUEUE_NAME);
}